home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / diskBoot.OpenProm / RCS / fsDisk.c,v < prev    next >
Text File  |  1992-05-07  |  15KB  |  454 lines

  1. head     1.12;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.12
  10. date     90.11.27.11.17.33;  author jhh;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @@
  17.  
  18.  
  19.  
  20. 1.12
  21. log
  22. @checked in with -k by kupfer at 92.05.07.13.02.47.
  23. @
  24. text
  25. @/* 
  26.  * fsDisk.c --
  27.  *
  28.  *    Routines related to managing local disks.  Each partition of a local
  29.  *    disk (partitions are defined by a table on the disk header) is
  30.  *    called a ``domain''.  FsAttachDisk attaches a domain into the file
  31.  *    system, and FsDeattachDisk removes it.  A domain is given
  32.  *    a number the first time it is ever attached.  This is recorded on
  33.  *    the disk so it doesn't change between boots.  The domain number is
  34.  *    used to identify disks, and a domain number plus a file number is
  35.  *    used to identify files.  Fsdm_DomainFetch is used to get the state
  36.  *    associated with a disk, and Fsdm_DomainRelease releases the reference
  37.  *    on the state.  FsDetachDisk checks the references on domains in
  38.  *    the normal (non-forced) case so that active disks aren't detached.
  39.  *
  40.  * Copyright 1987 Regents of the University of California
  41.  * All rights reserved.
  42.  * Permission to use, copy, modify, and distribute this
  43.  * software and its documentation for any purpose and without
  44.  * fee is hereby granted, provided that the above copyright
  45.  * notice appear in all copies.  The University of California
  46.  * makes no representations about the suitability of this
  47.  * software for any purpose.  It is provided "as is" without
  48.  * express or implied warranty.
  49.  */
  50.  
  51. #ifdef notdef
  52. static char rcsid[] = "$Header: /sprite/src/boot/sunprom/RCS/fsDisk.c,v 1.12 90/11/27 11:17:33 jhh Exp $ SPRITE (Berkeley)";
  53. #endif not lint
  54.  
  55.  
  56. #include "sprite.h"
  57.  
  58. #include "fsBoot.h"
  59. #include "devDiskLabel.h"
  60. #include "dev.h"
  61. #include "devFsOpTable.h"
  62. #include "machMon.h"
  63. #include "ofs.h"
  64. /*
  65.  * fsDevice is copied into all Fsio_FileIOHandles.  It is used by the drivers
  66.  * to get to the partition and geometry information for the disk.
  67.  */
  68. Fs_Device fsDevice;
  69.  
  70. /*
  71.  * fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
  72.  */
  73. static Fsdm_Domain fsDomain;
  74. Fsdm_Domain *fsDomainPtr = &fsDomain;
  75. static Fsio_FileIOHandle fsRootHandle;
  76. Fsio_FileIOHandle *fsRootHandlePtr = &fsRootHandle;
  77.  
  78. /*
  79.  * Forward declarations.
  80.  */
  81. static int    InstallLocalDomain();
  82. void        AddDomainFlags();
  83. static Boolean    IsSunLabel();
  84. static Boolean    IsSpriteLabel();
  85.  
  86. /*
  87.  *----------------------------------------------------------------------
  88.  *
  89.  * FsAttachDisk --
  90.  *
  91.  *    Make a particular local disk partition correspond to a prefix.
  92.  *    This makes sure the disk is up, reads the domain header,
  93.  *    and calls the initialization routine for the block I/O module
  94.  *    of the disk's driver.  By the time this is called the device
  95.  *    initialization routines have already been called from Dev_Config
  96.  *    so the device driver knows how the disk is partitioned into
  97.  *    domains.  This routine sees if the domain is formatted correctly,
  98.  *    and if so attaches it to the set of domains.
  99.  *
  100.  * Results:
  101.  *    SUCCESS if the disk was readable and had a good domain header.
  102.  *
  103.  * Side effects:
  104.  *    Sets up the Fsdm_DomainInfo for the domain.
  105.  *
  106.  *----------------------------------------------------------------------
  107.  */
  108. ReturnStatus
  109. FsAttachDisk(fsDevicePtr)
  110.     Fs_Device *fsDevicePtr;        /* Global FS device descriptor */
  111. {
  112.     ReturnStatus status;        /* Error code */
  113.     register Address buffer;        /* Read buffer */
  114.     int headerSector;            /* Starting sector of domain header */
  115.     int numHeaderSectors;        /* Number of sectors in domain header */
  116.     int summarySector;            /* Sector of summary information. */
  117.     Ofs_SummaryInfo *summaryInfoPtr;    /* Pointer to summary info. */
  118.     int amountRead;            /* Returned from read call */
  119.     int devType;            /* Device type index */
  120.     Fs_IOParam    io;            /* I/O Parameter block */
  121.     Fs_IOReply    reply;            /* Results of I/O */
  122.     int flags;
  123.  
  124.     /*
  125.      * Open the raw disk device so we can grub around in the header info.
  126.      */
  127.     devType = DEV_TYPE_INDEX(fsDevicePtr->type);
  128.     status = (*devFsOpTable[devType].open)(&fsDevice, FS_READ, 0, &flags);
  129.     if (status != SUCCESS) {
  130.     return(status);
  131.     }
  132.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  133.  
  134.     /*
  135.      * Read the zero'th sector of the partition.  It has a copy of the
  136.      * zero'th sector of the whole disk which describes how the rest of the
  137.      * domain's zero'th cylinder is layed out.
  138.      */
  139.     io.offset = 0;
  140.     io.length = DEV_BYTES_PER_SECTOR;
  141.     io.buffer = buffer;
  142.     status = (*devFsOpTable[devType].read)(&fsDevice, &io, &reply);
  143.     if (status != SUCCESS) {
  144.     return(status);
  145.     }
  146.     /*
  147.      * Check for different disk formats, and figure out how the rest
  148.      * of the zero'th cylinder is layed out.
  149.      */
  150.     if (((Sun_DiskLabel *)buffer)->magic == SUN_DISK_MAGIC) {
  151.     Ofs_DomainHeader    *domainHeaderPtr = (Ofs_DomainHeader *) buffer;
  152.     int            i;
  153.     /*
  154.      * For Sun formatted disks we put the domain header well past
  155.      * the disk label and the boot program.
  156.      */
  157.     numHeaderSectors = OFS_NUM_DOMAIN_SECTORS;
  158.     for (i = 2; i < FSDM_MAX_BOOT_SECTORS + 3; i+= FSDM_BOOT_SECTOR_INC) {
  159.         io.offset = i * DEV_BYTES_PER_SECTOR;
  160.         io.length = DEV_BYTES_PER_SECTOR * OFS_NUM_DOMAIN_SECTORS;
  161.         io.buffer = buffer;
  162.         status = (*devFsOpTable[devType].read)(&fsDevice, &io, &reply);
  163.         if (status != SUCCESS) {
  164.         return(status);
  165.         }
  166.         if (domainHeaderPtr->magic == OFS_DOMAIN_MAGIC) {
  167.         headerSector = i;
  168.         summarySector = i - 1;
  169.             break;
  170.         }
  171.     }
  172.     if (i >= FSDM_MAX_BOOT_SECTORS + 3) {
  173.         printf("Fsdm_AttachDisk: Can't find domain header.\n");
  174.         return(FAILURE);
  175.     }
  176.     } else {
  177.     printf("Disk label has bad magic number 0x%x\n", 
  178.         ((Sun_DiskLabel *)buffer)->magic);
  179.     return FAILURE;
  180.     }
  181.     ((Ofs_DomainHeader *) fsDomainPtr->clientData) = 
  182.     (Ofs_DomainHeader *) buffer;
  183.  
  184.      /*
  185.      * Set up the ClientData part of *devicePtr to reference the
  186.      * Ofs_Geometry part of the domain header.  This is used by the
  187.      * block I/O routines.
  188.      */
  189.     fsDevicePtr->data = (ClientData)
  190.     &((Ofs_DomainHeader *) fsDomainPtr->clientData)->geometry;
  191.  
  192.     /*
  193.      * Set up a file handle for the root directory.  What is important
  194.      * is the device info (for Block IO) and the file descriptor itself.
  195.      */
  196.     FsInitFileHandle(fsDomainPtr, FSDM_ROOT_FILE_NUMBER, fsRootHandlePtr);
  197.     return(SUCCESS);
  198. }
  199.  
  200. /*
  201.  *----------------------------------------------------------------------
  202.  * The following routines are used by device drivers to map from block
  203.  * and sector numbers to disk addresses.  There are two sets, one for
  204.  * drivers that use logical sector numbers (i.e. SCSI) and the other
  205.  * for <cyl,head,sector> format disk addresses.
  206.  *----------------------------------------------------------------------
  207.  */
  208.  
  209. /*
  210.  *----------------------------------------------------------------------
  211.  *
  212.  * Fs_BlocksToSectors --
  213.  *
  214.  *    Convert from block indexes (actually, fragment indexes) to
  215.  *    sectors using the geometry information on the disk.  This
  216.  *    is a utility for block device drivers.
  217.  *
  218.  * Results:
  219.  *    The sector number that corresponds to the fragment index.
  220.  *    The caller has to make sure that its I/O doesn't cross a
  221.  *    filesystem block boundary.
  222.  *
  223.  * Side effects:
  224.  *    None.
  225.  *
  226.  *----------------------------------------------------------------------
  227.  */
  228. #define SECTORS_PER_FRAG    (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
  229. #if defined(SCSI_DISK_BOOT) || defined(SUN_PROM_BOOT)
  230. int
  231. Fs_BlocksToSectors(fragNumber, data)
  232.     int fragNumber;    /* Fragment index to map into block index */
  233.     ClientData data;    /* ClientData from the device info */
  234. {
  235.     register Ofs_Geometry *geoPtr;
  236.     register int sectorNumber;    /* The sector corresponding to the fragment */
  237.     register int cylinder;    /* The cylinder number of the fragment */
  238.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  239.     register int blockNumber;    /* The block number within rotational set */
  240.  
  241.     geoPtr         = (Ofs_Geometry *)data;
  242.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  243.     if (geoPtr->blocksPerCylinder == 0) {
  244.     panic("blocksPerCylinder is 0");
  245.     }
  246.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  247.     if (geoPtr->rotSetsPerCyl > 0) {
  248.     /*
  249.      * Do fancy rotational set mapping.
  250.      */
  251.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  252.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  253.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  254.  
  255.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  256.               geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  257.               rotationalSet +
  258.               geoPtr->blockOffset[blockNumber];
  259.     sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  260.     } else {
  261.     /*
  262.      * Do straight-forward mapping.
  263.      */
  264.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  265.             fragNumber * SECTORS_PER_FRAG - cylinder * 
  266.             geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
  267.             SECTORS_PER_FRAG;
  268.     }
  269.  
  270.     return(sectorNumber);
  271. }
  272. #endif
  273.  
  274. /*
  275.  *----------------------------------------------------------------------
  276.  *
  277.  * Fs_BlocksToDiskAddr --
  278.  *
  279.  *    Convert from block indexes (actually, fragment indexes) to
  280.  *    disk address (head, cylinder, sector) using the geometry information
  281.  *     on the disk.  This is a utility for block device drivers.
  282.  *
  283.  * Results:
  284.  *    The disk address that corresponds to the disk address.
  285.  *    The caller has to make sure that its I/O doesn't cross a
  286.  *    filesystem block boundary.
  287.  *
  288.  * Side effects:
  289.  *    None.
  290.  *
  291.  *----------------------------------------------------------------------
  292.  */
  293. #ifdef XYLOGICS_BOOT
  294. void
  295. Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
  296.     int fragNumber;    /* Fragment index to map into block index */
  297.     ClientData data;    /* ClientData from the device info */
  298.     Dev_DiskAddr *diskAddrPtr;
  299. {
  300.     register Ofs_Geometry *geoPtr;
  301.     register int sectorNumber;    /* The sector corresponding to the fragment */
  302.     register int cylinder;    /* The cylinder number of the fragment */
  303.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  304.     register int blockNumber;    /* The block number within rotational set */
  305.  
  306.     geoPtr         = (Ofs_Geometry *)data;
  307.     /*
  308.      * Map to block number because the rotational sets are laid out
  309.      * relative to blocks.  After that the cylinder is easy because we know
  310.      * blocksPerCylinder.  To get the head and sector we first get the
  311.      * rotational set (described in fsDisk.h) of the block and the
  312.      * block's sector offset (relative to the rotational set!).  This complex
  313.      * algorithm crops up because there isn't necessarily an even number
  314.      * of blocks per track.  The 'blockOffset' array in the geometry gives
  315.      * a sector index of each successive block in a rotational set. Finally,
  316.      * we can use the sectorsPerTrack to get the head and sector.
  317.      */
  318.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  319.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  320.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  321.     diskAddrPtr->cylinder = cylinder;
  322.  
  323.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  324.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  325. /*
  326.  * The follow statment had to be broken into two because the compiler used
  327.  * register d2 to do the modulo operation, but wasn't saving its value.
  328.  */
  329.     sectorNumber    = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  330.               rotationalSet + geoPtr->blockOffset[blockNumber];
  331.     sectorNumber    +=
  332.             (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  333.  
  334.     diskAddrPtr->head    = sectorNumber / geoPtr->sectorsPerTrack;
  335.     diskAddrPtr->sector = sectorNumber -
  336.               diskAddrPtr->head * geoPtr->sectorsPerTrack;
  337. }
  338. #endif
  339.  
  340. /*
  341.  *----------------------------------------------------------------------
  342.  *
  343.  * Fs_SectorsToRawDiskAddr --
  344.  *
  345.  *      Convert from a sector offset to a raw disk address (cyl, head,
  346.  *      sector) using the geometry information on the disk.  This is a
  347.  *      utility for raw device drivers and does not pay attention to the
  348.  *      rotational position of filesystem disk blocks.
  349.  *
  350.  *    This should be moved to Dev
  351.  *
  352.  * Results:
  353.  *    The disk address that corresponds exactly to the byte offset.
  354.  *
  355.  * Side effects:
  356.  *    None.
  357.  *
  358.  *----------------------------------------------------------------------
  359.  */
  360. #ifdef XYLOGICS_BOOT
  361. int
  362. Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
  363.     int sector;        /* Sector number (counting from zero 'til the total
  364.              * number of sectors in the disk) */
  365.     int numSectors;    /* Number of sectors per track */
  366.     int numHeads;    /* Number of heads on the disk */
  367.     Dev_DiskAddr *diskAddrPtr;
  368. {
  369.     register int sectorsPerCyl;    /* The rotational set with cylinder of frag */
  370.  
  371.     sectorsPerCyl        = numSectors * numHeads;
  372.     diskAddrPtr->cylinder    = sector / sectorsPerCyl;
  373.     sector            -= diskAddrPtr->cylinder * sectorsPerCyl;
  374.     diskAddrPtr->head        = sector / numSectors;
  375.     diskAddrPtr->sector        = sector - numSectors * diskAddrPtr->head;
  376. }
  377. #endif
  378.  
  379.  
  380. /*
  381.  *----------------------------------------------------------------------
  382.  *
  383.  * FsDeviceBlockIO --
  384.  *
  385.  *    Map a file system block address to a block device block address 
  386.  *    perform the requested operation.
  387.  *
  388.  * NOTE: This routine is temporary and should be replaced when the file system
  389.  *     is converted to use the async block io interface.
  390.  *
  391.  * Results:
  392.  *    The return status of the operation.
  393.  *
  394.  * Side effects:
  395.  *    Blocks may be written or read.
  396.  *
  397.  *----------------------------------------------------------------------
  398.  */
  399.  
  400. ReturnStatus
  401. FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
  402.     int readWriteFlag;        /* FS_READ or FS_WRITE */
  403.     Fs_Device *devicePtr;    /* Specifies device type to do I/O with */
  404.     int fragNumber;        /* CAREFUL, fragment index, not block index.
  405.                  * This is relative to start of device. */
  406.     int numFrags;        /* CAREFUL, number of fragments, not blocks */
  407.     Address buffer;        /* I/O buffer */
  408. {
  409.     ReturnStatus status;    /* General return code */
  410.     int firstSector;        /* Starting sector of transfer */
  411.     DevBlockDeviceRequest    request;
  412.     int                transferCount;
  413.     int                devType;
  414.     Fs_IOParam            io;        
  415.     Fs_IOReply            reply;    
  416.  
  417.     devType = DEV_TYPE_INDEX(devicePtr->type);
  418.     if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
  419.     /*
  420.      * The I/O doesn't start on a block boundary.  Transfer the
  421.      * first few extra fragments to get things going on a block boundary.
  422.      */
  423.     register int extraFrags;
  424.  
  425.     extraFrags = FS_FRAGMENTS_PER_BLOCK -
  426.             (fragNumber % FS_FRAGMENTS_PER_BLOCK);
  427.     if (extraFrags > numFrags) {
  428.         extraFrags = numFrags;
  429.     }
  430.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  431.     io.offset = firstSector * DEV_BYTES_PER_SECTOR;
  432.     io.length = extraFrags * FS_FRAGMENT_SIZE;
  433.     io.buffer = buffer;
  434.     status = (*devFsOpTable[devType].read)(devicePtr, &io, &reply);
  435.     extraFrags = reply.length / FS_FRAGMENT_SIZE;
  436.     fragNumber += extraFrags;
  437.     buffer += reply.length;
  438.     numFrags -= extraFrags;
  439.     }
  440.     if (numFrags > 0) {
  441.     /*
  442.      * Transfer the left over fragments.
  443.      */
  444.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  445.     io.offset = firstSector * DEV_BYTES_PER_SECTOR;
  446.     io.length = numFrags * FS_FRAGMENT_SIZE;
  447.     io.buffer = buffer;
  448.     status = (*devFsOpTable[devType].read)(devicePtr, &io, &reply);
  449.     }
  450.     return(status);
  451. }
  452.  
  453. @
  454.